<template>
  <div class="bpmn-container">
    <div class="viewer" ref="viewer"></div>
    <div class="legend">
      <div class="legend-item">
        <div class="legend-color current"></div>
        <span>当前任务</span>
      </div>
      <div class="legend-item">
        <div class="legend-color completed"></div>
        <span>已完成任务</span>
      </div>
      <div class="legend-item">
        <div class="legend-color rejected"></div>
        <span>已拒绝任务</span>
      </div>
    </div>

    <!-- 任务历史信息弹窗 -->
    <el-dialog 
      v-model="historyDialogVisible" 
      :title="historyDialogTitle" 
      width="500px"
    >
      <div v-if="selectedTaskHistory.length">
        <el-timeline>
          <el-timeline-item
            v-for="(record, index) in selectedTaskHistory"
            :key="index"
            :color="getTimelineItemColor(record.action)"
            :timestamp="formatTime(record.timestamp)"
          >
            <b>{{ record.user }}</b> {{ getActionText(record.action) }}
            <div v-if="record.comment" class="comment-box">
              {{ record.comment }}
            </div>
          </el-timeline-item>
        </el-timeline>
      </div>
      <div v-else class="empty-history">
        暂无审批历史记录
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import BpmnViewer from 'bpmn-js/lib/NavigatedViewer'
import 'bpmn-js/dist/assets/diagram-js.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'

export default {
  name: 'BpmnViewer',
  props: {
    xml: {
      type: String,
      required: true
    }
  },
  setup(props) {
    const viewer = ref(null)
    let bpmnViewer = null
    const historyDialogVisible = ref(false)
    const historyDialogTitle = ref('任务审批历史')
    const selectedTaskHistory = ref([])

    const initViewer = async () => {
      if (!viewer.value) return
      
      try {
        // 初始化查看器
        bpmnViewer = new BpmnViewer({
          container: viewer.value
        })

        // 导入XML
        await bpmnViewer.importXML(props.xml)
        
        // 调整视图
        bpmnViewer.get('canvas').zoom('fit-viewport')
        
        // 应用自定义样式
        applyCustomStyles()
        
        // 添加事件监听
        setupEventListeners()
      } catch (error) {
        console.error('加载BPMN图失败:', error)
      }
    }

    const setupEventListeners = () => {
      const eventBus = bpmnViewer.get('eventBus')
      
      // 监听元素点击事件
      eventBus.on('element.click', (event) => {
        const { element } = event
        
        // 如果点击的是任务
        if (element.type.includes('Task')) {
          showTaskHistory(element)
        }
      })
    }
    
    const showTaskHistory = (element) => {
      // 获取任务历史记录
      const historyJson = element.businessObject.get('history')
      const taskName = element.businessObject.name || element.id
      
      historyDialogTitle.value = `任务"${taskName}"的审批历史`
      
      if (historyJson) {
        try {
          selectedTaskHistory.value = JSON.parse(historyJson)
          historyDialogVisible.value = true
        } catch (e) {
          console.error('解析任务历史记录失败:', e)
          selectedTaskHistory.value = []
        }
      } else {
        selectedTaskHistory.value = []
        historyDialogVisible.value = true
      }
    }
    
    const formatTime = (timestamp) => {
      if (!timestamp) return ''
      
      const date = new Date(timestamp)
      return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`
    }
    
    const getActionText = (action) => {
      const actionTexts = {
        'approve': '审批通过了任务',
        'reject': '拒绝了任务',
        'complete': '完成了任务'
      }
      return actionTexts[action] || action
    }
    
    const getTimelineItemColor = (action) => {
      const colors = {
        'approve': '#67C23A',
        'complete': '#67C23A',
        'reject': '#F56C6C'
      }
      return colors[action] || '#909399'
    }

    const applyCustomStyles = () => {
      if (!bpmnViewer) return
      
      const canvas = bpmnViewer.get('canvas')
      const elementRegistry = bpmnViewer.get('elementRegistry')
      
      // 获取所有任务元素
      const allElements = elementRegistry.getAll()
      const taskElements = allElements.filter(element => 
        element.type.includes('Task') || element.type === 'bpmn:UserTask'
      )
      
      taskElements.forEach(task => {
        const element = elementRegistry.get(task.id)
        if (element) {
          // 根据任务状态添加不同样式
          const status = element.businessObject.get('status')
          
          if (status === 'completed' || element.businessObject.get('completed')) {
            canvas.addMarker(task.id, 'completed')
          } else if (status === 'rejected' || element.businessObject.get('rejected')) {
            canvas.addMarker(task.id, 'rejected')
          } else if (status === 'pending' || element.businessObject.get('current')) {
            canvas.addMarker(task.id, 'current')
          }
          
          // 添加处理人标签
          const assignee = element.businessObject.get('assignee')
          if (assignee) {
            const overlays = bpmnViewer.get('overlays')
            overlays.add(task.id, {
              position: {
                bottom: 0,
                right: 0
              },
              html: `<div class="assignee-label">${assignee}</div>`
            })
          }
          
          // 添加历史记录指示器
          const history = element.businessObject.get('history')
          if (history) {
            const overlays = bpmnViewer.get('overlays')
            overlays.add(task.id, {
              position: {
                top: 0,
                right: 0
              },
              html: `<div class="history-indicator" title="点击查看历史记录"><i class="el-icon-time"></i></div>`
            })
          }
        }
      })
    }

    onMounted(() => {
      initViewer()
    })

    onBeforeUnmount(() => {
      if (bpmnViewer) {
        bpmnViewer.destroy()
      }
    })

    // 监听xml变化
    watch(() => props.xml, () => {
      initViewer()
    })

    return {
      viewer,
      historyDialogVisible,
      historyDialogTitle,
      selectedTaskHistory,
      formatTime,
      getActionText,
      getTimelineItemColor
    }
  }
}
</script>

<style scoped>
.bpmn-container {
  width: 100%;
  height: 600px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: auto;
  position: relative;
}

.viewer {
  width: 100%;
  height: 100%;
  min-height: 600px;
}

.legend {
  position: absolute;
  top: 10px;
  right: 10px;
  background: white;
  padding: 10px;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
  z-index: 1000;
}

.legend-item {
  display: flex;
  align-items: center;
  margin-bottom: 5px;
}

.legend-color {
  width: 20px;
  height: 20px;
  margin-right: 8px;
  border-radius: 3px;
}

.legend-color.current {
  background-color: #ecf5ff;
  border: 2px solid #409EFF;
}

.legend-color.completed {
  background-color: #f0f9eb;
  border: 2px solid #67C23A;
}

.legend-color.rejected {
  background-color: #fef0f0;
  border: 2px solid #F56C6C;
}

/* 处理人标签样式 */
:deep(.assignee-label) {
  background-color: rgba(255, 255, 255, 0.8);
  padding: 2px 5px;
  border-radius: 3px;
  font-size: 12px;
  color: #606266;
  border: 1px solid #dcdfe6;
}

/* 历史记录指示器样式 */
:deep(.history-indicator) {
  background-color: rgba(255, 255, 255, 0.8);
  padding: 2px;
  border-radius: 50%;
  font-size: 12px;
  color: #409EFF;
  border: 1px solid #dcdfe6;
  cursor: pointer;
  width: 18px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
}

:deep(.history-indicator:hover) {
  background-color: #ecf5ff;
}

/* 评论框样式 */
.comment-box {
  background-color: #f5f7fa;
  padding: 8px;
  border-radius: 4px;
  margin-top: 5px;
  font-size: 13px;
  border-left: 3px solid #909399;
}

/* 空历史记录 */
.empty-history {
  text-align: center;
  color: #909399;
  padding: 20px;
}

/* BPMN高亮样式 */
:deep(.completed) {
  stroke: #67C23A !important;
  fill: #f0f9eb !important;
}

:deep(.current) {
  stroke: #409EFF !important;
  fill: #ecf5ff !important;
  stroke-width: 2px !important;
}

:deep(.rejected) {
  stroke: #F56C6C !important;
  fill: #fef0f0 !important;
}
</style> 